<!DOCTYPE html>
<!--

// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

-->
<html>
<head>
<title>Traceur</title>

<script src="../src/traceur.js"></script>
<style>

@import url(http://fonts.googleapis.com/css?family=Droid+Sans+Mono);
@import url(http://fonts.googleapis.com/css?family=Droid+Sans);

html, body {
  height: 100%;
  margin: 0;
}

textarea {
  display: block;
  width: 100%;
  height: 50%;
  margin: 0;
  border:  0;
  border-bottom: 1px solid #aaa;
  box-sizing: border-box;
  padding: 5px;
}

textarea,
pre {
  font: 12px 'Droid Sans Mono', sans-serif;
}

.error {
  color: red;
}

pre{
  margin: 5px;
}

.option-button {
  background: black;
  border: 0;
  border-bottom-left-radius: 5px;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, .5);
  color: white;
  font: 13px/20px 'Droid Sans', sans-serif;
  height: 25px;
  margin: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.options {
  background: black;
  border-radius: 5px 0 5px 5px;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, .5);
  color: white;
  font: 13px/20px 'Droid Sans', sans-serif;
  padding: 10px;
  position: absolute;
  right: 0;
  top: 20px;
}

.options label {
  display: block;
}

.options label > input {
  vertical-align: -2px;
  margin: 0 1ex 0 0;
}

.options hr {
  background: white;
  border: 0;
  height: 1px;
}

</style>
</head>
<body>
<textarea class="input"></textarea>
<pre class="error"></pre>
<pre class="eval"></pre>

<pre class="output"></pre>
<pre class="source-map"></pre>
<button class="option-button">Options</button>
<div class="options" hidden>
<label><input class="eval" type="checkbox" checked>Evaluate</label>
<label><input class="output" type="checkbox" checked>Show generated code</label>
<hr>
<div class="traceur-options"></div>
<button class="all-on">All Options On</button>
<button class="all-off">All Options Off</button>
</div>

<script>

(function() {
  'use strict';

  var SourceMapConsumer = traceur.outputgeneration.SourceMapConsumer;
  var SourceMapGenerator = traceur.outputgeneration.SourceMapGenerator;
  var ProjectWriter = traceur.outputgeneration.ProjectWriter;

  var hasError = false;
  var input = document.querySelector('.input');
  var outputCheckbox = document.querySelector('input.output');
  var output = document.querySelector('pre.output');
  var evalCheckbox = document.querySelector('input.eval');
  var evalElement = document.querySelector('pre.eval');
  var errorElement = document.querySelector('pre.error');
  var sourceMapElement = document.querySelector('pre.source-map');

  evalCheckbox.addEventListener('click', function(e) {
    evalElement.hidden = !evalCheckbox.checked;
  }, false);

  outputCheckbox.addEventListener('click', function(e) {
    output.hidden = !outputCheckbox.checked;
  }, false);

  function compile() {
    hasError = false;
    output.textContent = errorElement.textContent = '';

    var reporter = new traceur.util.ErrorReporter();
    reporter.reportMessageInternal = function(location, kind, format, args) {
      var i = 0;
      var message = format.replace(/%s/g, function() {
        return args[i++];
      });
      if (location)
        format = location + ': ' + message;
      errorElement.textContent += format + '\n';
    };

    var url = window.location.href;
    var project = new traceur.semantics.symbols.Project(url);
    var name = 'repl';
    var contents = input.value;
    var sourceFile = new traceur.syntax.SourceFile(name, contents);
    project.addFile(sourceFile);
    var res = traceur.codegeneration.Compiler.compile(reporter, project, false);
    if (reporter.hadError()) {
      hasError = true;
    } else {
      var options;
      if (traceur.options.sourceMaps) {
        var config = {file: 'traceured.js'};
        var sourceMapGenerator = new SourceMapGenerator(config);
        options = {sourceMapGenerator: sourceMapGenerator};
      } 

      var source = output.textContent = ProjectWriter.write(res, options);
          
      if (evalCheckbox.checked) {
        try {
          evalElement.textContent = ('global', eval)(source);
        } catch(ex) {
          hasError = true;
          errorElement.textContent = ex;
        }
      }
      
      if (traceur.options.sourceMaps) {
        var renderedMap = renderSourceMap(source, options.sourceMap);
        sourceMapElement.textContent = renderedMap;
      }
    }

    errorElement.hidden = !hasError;
  }

  input.addEventListener('input', compile, false);

  function createOptionRow(name) {
    var label = document.createElement('label');
    label.textContent = name;
    var cb = label.insertBefore(document.createElement('input'),
                                label.firstChild);
    cb.type = 'checkbox';
    var checked = traceur.options[name];
    cb.checked = checked;
    cb.indeterminate = checked === null;
    cb.onclick = function() {
      traceur.options[name] = cb.checked;
      createOptions();
      compile();
    };
    return label;
  }

  function createOptions() {
    var optionsDiv = document.querySelector('.traceur-options');
    optionsDiv.textContent = '';
    Object.keys(traceur.options).forEach(function(name) {
      if (name === 'blockBinding' || name == 'debug') {
        optionsDiv.appendChild(document.createElement('hr'));
      }
      optionsDiv.appendChild(createOptionRow(name));
    });
  }

  createOptions();

  function rebuildOptions() {
    var optionsDiv = document.querySelector('.traceur-options');
    optionsDiv.innerHTML = '';
    createOptions();
  }
  
  document.querySelector('.all-on').addEventListener('click',
      function() {
        traceur.options.reset();
        rebuildOptions();
      });

  document.querySelector('.all-off').addEventListener('click', 
    function() {
      traceur.options.reset(true);
      rebuildOptions();
    });
  
  document.querySelector('.option-button').addEventListener('click',
      function() {
        var optionsDiv = document.querySelector('.options');
        optionsDiv.hidden = !optionsDiv.hidden;
      });
      
  function renderSourceMap(source, sourceMap) {
    var consumer = new SourceMapConsumer(sourceMap);
    var lines = source.split('\n');
    var lineNumberTable = lines.map(function(line, lineNo) {
      var generatedPosition = {
        line: lineNo + 1, 
        column: 0
      };
      var position = consumer.originalPositionFor(generatedPosition);
      var lineDotColumn = position.line + '.' + position.column;
      return (lineNo + 1) + ': ' + line + ' -> ' + lineDotColumn;
    });
    return 'SourceMap:\n' + lineNumberTable.join('\n');
  }
  
})();

</script>
</body>
</html>
